Pivy es una biblioteca de enlace Python para Coin, la biblioteca de renderizado 3D utilizada en FreeCAD para mostrar objetos en una vista 3D. Coin es una implementación de código abierto de la especificación "Open Inventor" para el manejo de gráficos. Por lo tanto, en FreeCAD, los términos "Pivy", "Coin" u "Open Inventor" se refieren esencialmente a lo mismo.
Cuando se importa en un intérprete de Python en ejecución, Pivy nos permite comunicarnos directamente con cualquier escenógrafo de Coin en ejecución, como la vista 3D, o incluso crear nuevas. No se necesita a Pivy para compilar FreeCAD, pero sí lo es en tiempo de ejecución cuando se utilizan entornos de trabajo basados en Python que crean formas en pantalla, como el Entorno de Trabajo Borrador y el Entorno de Trabajo BIM. Por este motivo, Pivy se instala normalmente al instalar una distribución de FreeCAD.
La biblioteca Coin se divide en varias partes: Coin propiamente dicho, para manipular grafos de escena, y enlaces para diversos sistemas de interfaz gráfica de usuario (GUI), como Windows y Qt. Si están presentes en el sistema, estos módulos también están disponibles para Pivy. El módulo Coin siempre está presente, y es el que utilizaremos, ya que no necesitaremos preocuparnos por integrar nuestra visualización 3D en ninguna interfaz; FreeCAD ya se encarga de ello. Lo único que debemos hacer es lo siguiente:
from pivy import coin
En la página Escenógrafo ya se vio cómo se organiza una escena típica de Coin. Todo lo que aparece en una vista 3D es un escenógrafo de Coin, organizado de la misma manera. Tenemos un nodo raíz, y todos los objetos en la pantalla son sus hijos.
FreeCAD ofrece una forma sencilla de acceder al nodo raíz de un grafo de escena de la vista 3D:
sg = FreeCADGui.ActiveDocument.ActiveView.getSceneGraph()
print(sg)
Esto devolverá el nodo raíz:
<pivy.coin.SoSelection; proxy of <Swig Object of type 'SoSelection *' at 0x360cb60> >
Podemos inspeccionar los elementos secundarios inmediatos de nuestra escena:
for node in sg.getChildren():
print(node)
Algunos de estos nodos, como SoSeparator o SoGroup, pueden tener nodos hijos. La lista completa de los objetos Coin disponibles se encuentra en la documentación oficial de Coin.
Ahora, vamos a intentar añadir algo a nuestro grafo de escena. Añadiremos un bonito cubo rojo:
col = coin.SoBaseColor()
col.rgb = (1, 0, 0)
cub = coin.SoCube()
myCustomNode = coin.SoSeparator()
myCustomNode.addChild(col)
myCustomNode.addChild(cub)
sg.addChild(myCustomNode)
Ahora, probemos esto:
col.rgb = (1, 1, 0)
Como puede ver, todo sigue siendo accesible y modificable sobre la marcha. No es necesario recalcular ni redibujar nada; Coin se encarga de todo. Puede añadir elementos a su grafo de escena, cambiar propiedades, ocultarlos, mostrar objetos temporales, lo que quiera. Por supuesto, esto solo afecta a la visualización en la vista 3D. FreeCAD recalcula dicha visualización al abrir el archivo y cuando un objeto necesita ser recalculado. Por lo tanto, si cambia la apariencia de un objeto de FreeCAD existente, esos cambios se perderán si el objeto se recalcula o al volver a abrir el archivo.
Como ya se mencionó anteriomente, el orden es muy importante en un grafo de escena de openInventor. Un nodo afecta lo que viene después. Por ejemplo, si queremos tener la capacidad de mover nuestro cubo, necesitaremos agregar un nodo SoTranslation before al cubo:
col = coin.SoBaseColor()
col.rgb = (1, 0, 0)
trans = coin.SoTranslation()
trans.translation.setValue([0, 0, 0])
cub = coin.SoCube()
myCustomNode = coin.SoSeparator()
myCustomNode.addChild(col)
myCustomNode.addChild(trans)
myCustomNode.addChild(cub)
sg.addChild(myCustomNode)
Para mover nuestro cubo ahora podemos hacer lo siguiente:
trans.translation.setValue([2, 0, 0])
Finalmente, la eliminación de algo se lleva a cabo con:
sg.removeChild(myCustomNode)
Un mecanismo de devolución de llamada es un sistema que permite que una biblioteca, como nuestra biblioteca Coin, le llame, es decir, que ejecute una función específica desde su objeto Python en ejecución. De esta forma, Coin puede notificarle que ha ocurrido un evento concreto en la escena. Coin puede monitorizar diversas cosas, como la posición del ratón, los clics de los botones del ratón, las teclas pulsadas y mucho más.
FreeCAD ofrece una forma sencilla de utilizar dichas funciones de devolución de llamada:
from pivy import coin
class ButtonTest:
def __init__(self):
self.view = FreeCADGui.ActiveDocument.ActiveView
self.callback = self.view.addEventCallbackPivy(coin.SoMouseButtonEvent.getClassTypeId(), self.getMouseClick)
def getMouseClick(self, event_cb):
event = event_cb.getEvent()
if event.getState() == coin.SoMouseButtonEvent.DOWN:
print("Alert!!! A mouse button has been improperly clicked!!!")
self.view.removeEventCallbackPivy(coin.SoMouseButtonEvent.getClassTypeId(), self.callback)
ButtonTest()
La llamada de retorno debe iniciarse desde un objeto, ya que dicho objeto debe seguir en ejecución cuando se produzca la llamada.
Consulte también la lista completa de los posibles eventos y sus parámetros, o la documentación oficial de Coin.
Lamentablemente, Pivy no cuenta con su propia documentación. Sin embargo, dado que es una interfaz precisa para la biblioteca Coin, puede consultar la documentación de referencia de C++ para obtener información. En este caso, deberá adaptar el estilo de nomenclatura de clases de C++ al estilo de Python.
En C++:
SoFile::getClassTypeId()
En Pivy:
SoFile.getClassId()
Estos enlaces proporcionan documentación de referencia para Coin v3.x. Las diferencias con la versión v4.x son mínimas, por lo que aún pueden resultar útiles.